/****************************************************************************
 **
 ** This file is part of the yFiles extension package GraphML-3.2-yFiles-2.7.
 ** 
 ** yWorks proprietary/confidential. Use is subject to license terms.
 **
 ** Redistribution of this file or of an unauthorized byte-code version
 ** of this file is strictly forbidden.
 **
 ** Copyright (c) 2000-2009 by yWorks GmbH, Vor dem Kreuzberg 28, 
 ** 72070 Tuebingen, Germany. All rights reserved.
 **
 ***************************************************************************/

package demo.yext.graphml;


import org.graphdrawing.graphml.attr.AttributeConstants;
import y.base.DataMap;
import y.base.Edge;
import y.base.EdgeMap;
import y.base.Graph;
import y.base.Node;
import y.base.NodeMap;
import y.option.OptionHandler;
import y.util.Maps;
import y.view.EditMode;
import y.view.PopupMode;
import y.view.ViewMode;
import y.view.HitInfo;
import yext.graphml.graph2D.GraphMLIOHandler;

import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import java.awt.event.ActionEvent;
import java.util.HashMap;


/**
 * This demo shows how to configure GraphMLIOHandler to be able to handle
 * extra node, edge and graph data of simple type.
 * Additional data for a node and edge can be edited by right-clicking on the corresponding
 * element. To edit the graph data, right-click on the canvas background.
 * The element tooltip will show the currently set data values for each element.
 */
public class CustomGraphMLDemo extends GraphMLDemo {

  /** stores a boolean value for each node **/
  NodeMap node2BoolMap;

  /** stores an int value for each edge **/
  EdgeMap edge2IntMap;

  /** stores an String value for the graph **/
  DataMap graph2StringMap;

  public CustomGraphMLDemo() {

    //define a view mode that displays the currently set data values
    ViewMode tooltipMode = new ViewMode() {
      public void mouseMoved(double x, double y) {
        HitInfo info = getHitInfo(x,y);
        if (info.getHitNode() != null) {
          view.setToolTipText("Node:BooleanValue=" + node2BoolMap.getBool(info.getHitNode()));
        } else if (info.getHitEdge() != null) {
          view.setToolTipText("Edge:IntValue=" + edge2IntMap.getInt(info.getHitEdge()));
        } else {
          view.setToolTipText("Graph:StringValue=" + graph2StringMap.get(view.getGraph2D()));
        }
      }
    };
    //add the view mode to the view
    view.addViewMode(tooltipMode);
  }

  /**
   * Configures GraphMLIOHandler to read and write additional node, edge and graph data
   * of a simple type.
   */
  protected GraphMLIOHandler createGraphMLIOHandler() {
    GraphMLIOHandler ioHandler = super.createGraphMLIOHandler();

    Graph graph = view.getGraph2D();

    node2BoolMap = graph.createNodeMap();
    ioHandler.addAttribute(node2BoolMap, "BooleanValue", AttributeConstants.TYPE_BOOLEAN);

    edge2IntMap = graph.createEdgeMap();
    ioHandler.addAttribute(edge2IntMap, "IntValue", AttributeConstants.TYPE_INT);

    graph2StringMap = Maps.createDataMap(new HashMap());
    ioHandler.addGraphAttribute(graph2StringMap, graph2StringMap, "StringValue", AttributeConstants.TYPE_STRING);

    return ioHandler;
  }


  /**
   * Create an edit mode that displays a context-sensitive popup-menu when right-clicking
   * on an the canvas.
   */
  protected EditMode createEditMode() {
    EditMode editMode = super.createEditMode();

    editMode.setPopupMode(new PopupMode() {
      public JPopupMenu getNodePopup(Node v) {
        JPopupMenu pm = new JPopupMenu();
        pm.add(new EditAttributeAction("Edit Node Attribute...", v, node2BoolMap, AttributeConstants.TYPE_BOOLEAN));
        return pm;
      }

      public JPopupMenu getEdgePopup(Edge e) {
        JPopupMenu pm = new JPopupMenu();
        pm.add(new EditAttributeAction("Edit Edge Attribute...", e, edge2IntMap, AttributeConstants.TYPE_INT));
        return pm;
      }

      public JPopupMenu getPaperPopup(double x, double y) {
        JPopupMenu pm = new JPopupMenu();
        pm.add(new EditAttributeAction("Edit Graph Attribute...", getGraph2D(), graph2StringMap, AttributeConstants.TYPE_STRING));
        return pm;
      }
    });

    return editMode;
  }


  /**
   * Editor action for the additional node, edge and graph attributes.
   */
  static class EditAttributeAction extends AbstractAction {
    private Object object;
    private DataMap dataMap;
    private int dataType;

    private OptionHandler op;

    EditAttributeAction(String name, Object object, DataMap dataMap, int dataType) {
      super(name);
      this.object = object;
      this.dataMap = dataMap;
      this.dataType = dataType;
      op = new OptionHandler(name);
      if (dataType == AttributeConstants.TYPE_BOOLEAN) {
        op.addBool("Boolean Value", dataMap.getBool(object));
      } else if (dataType == AttributeConstants.TYPE_INT) {
        op.addInt("Integer Value", dataMap.getInt(object));
      } else if (dataType == AttributeConstants.TYPE_STRING) {
        op.addString("String Value", (String) dataMap.get(object));
      }
    }

    public void actionPerformed(ActionEvent actionEvent) {
      if (op.showEditor()) {
        if (dataType == AttributeConstants.TYPE_BOOLEAN) {
          dataMap.setBool(object, op.getBool("Boolean Value"));
        } else if (dataType == AttributeConstants.TYPE_INT) {
          dataMap.setInt(object, op.getInt("Integer Value"));
        } else if (dataType == AttributeConstants.TYPE_STRING) {
          dataMap.set(object, op.getString("String Value"));
        }
      }
    }
  }

  /**
   * Add sample graphs to the menu.
   */
  protected JMenu createSampleGraphMenu() {
    return createSampleGraphMenu(new String[]{"resources/custom/demo.graphml"});
  }

  /**
   * Launches this demo.
   */
  public static void main(String[] args) {
    initLnF();
    final CustomGraphMLDemo demo = new CustomGraphMLDemo();
    demo.start();
  }
}
